
#ifndef RTHTTPHEAD_H
#define RTHTTPHEAD_H

#include "RtHttpUtilClasses.h"

class /*RT_API_EXPORT*/ CRtHttpHeaderArray 
{
public:
	CRtHttpHeaderArray();
	virtual ~CRtHttpHeaderArray();

	BOOL PeekHeader(const CRtHttpAtom &aHeader) const;
	BOOL SetHeader(const CRtHttpAtom &aHeader, const CRtString &aValue);
    BOOL GetHeader(const CRtHttpAtom &aHeader, CRtString &aValue) const;

	BOOL CanAppendToHeader(const CRtHttpAtom &aHeader) const;
	BOOL HaveAllHeaders() { return m_bHaveAllHeaders; }

	// parse line whose format is <CRtHttpAtom : CRtString>.
	BOOL ParseHeaderLine(
		LPCSTR aLine, 
		CRtHttpAtom *aAtom = NULL, 
		CRtString *aValue = NULL);

	// Mainly for parse HTTP request and response.
	BOOL ParseLine(const CRtString &aLine);

	LONG GetContentLength();
	void SetMaxContentLength(LONG inLength) { m_maxContentLength = inLength; }
	LONG GetMaxContentLength() const { return m_maxContentLength; }

	virtual BOOL Clear();

	static LPCSTR s_szHttpHeaderNewLine;

protected:
	virtual BOOL ParseFirstLine_t(LPCSTR aLine);

	void Flatten(CRtString &aFlattened) const;

	BOOL m_bHaveAllHeaders;
	BOOL m_bHaveFirstLine;

	BOOL m_checkContentLength;
	LONG m_maxContentLength;

private:
	struct CEntry
	{
		CEntry() { }
		CEntry(const CRtHttpAtom &aHeader, const CRtString &aVal)
			: m_atomHeader(aHeader), m_strValue(aVal) 
		{ }

		friend bool operator == (
			const CEntry &aAtom1, 
			const CEntry &aAtom2) 
		{ 
			return true; 
		}
		
		friend bool operator < (
			const CEntry &aAtom1, 
			const CEntry &aAtom2) 
		{ 
			return true; 
		}

		CRtHttpAtom m_atomHeader;
		CRtString  m_strValue;
	};
	typedef std::vector<CEntry> CWbxHEntryVectorType;
	void LookupEntry(const CRtHttpAtom &aHeader, CEntry *&aEntry) const;
	CWbxHEntryVectorType m_Headers;
};

class /*RT_API_EXPORT*/ CRtHttpRequestHead : public CRtHttpHeaderArray
{
public:
	CRtHttpRequestHead();
	virtual ~CRtHttpRequestHead();

	BOOL SetMethod(const CRtHttpAtom &aAtom);
	CRtHttpAtom GetMethod() { return m_atMethod; }

	void SetVersion(CRtHttpVersion aVer) { m_nVersion = aVer; }
	CRtHttpVersion GetVersion() { return m_nVersion; }

	void SetRequestURI(const CRtString &aURL) { m_strRequestURI = aURL; }
	CRtString GetRequestURI() { return m_strRequestURI; }
/*
	BOOL AllowContentBody() const 
	{ 
		RT_ASSERTE(m_bHaveAllHeaders);
		return !(m_atMethod==CRtHttpAtomList::Get); 
	}
*/
	
	CRtString Flatten() const;

	virtual BOOL Clear();

protected:
	virtual BOOL ParseFirstLine_t(LPCSTR aLine);
	
private:
	CRtHttpAtom		m_atMethod;
	CRtHttpVersion	m_nVersion;
	CRtString		m_strRequestURI;
};

class /*RT_API_EXPORT*/ CRtHttpResponseHead : public CRtHttpHeaderArray
{
public:
	CRtHttpResponseHead();
	virtual ~CRtHttpResponseHead();

	LONG GetStatus() { return m_nStatus; }
	void SetStatus(LONG aStatus) { m_nStatus = aStatus; }

	CRtString GetStatusText() { return m_strStatusText; }
	void SetStatusText(const CRtString& aText) { m_strStatusText = aText; }

	CRtHttpVersion GetVerion() { return m_nVersion; }
	void SetVerion(CRtHttpVersion aVer) { m_nVersion = aVer; }

	LONG GetContentLength();
/*
	BOOL AllowContentBody() const 
	{ 
		RT_ASSERTE(m_bHaveAllHeaders);
		return !((m_nStatus>=100 && m_nStatus<200) || m_nStatus==204 || m_nStatus==304); 
	}
*/

	CRtString Flatten() const;

	virtual BOOL Clear();

protected:
	virtual BOOL ParseFirstLine_t(LPCSTR aLine);

private:
//	BOOL HaveStateLine() { return m_bHaveFirstLine; }

	CRtHttpVersion	m_nVersion;
	LONG			m_nStatus;
	CRtString		m_strStatusText;
	CRtString		m_strContentType;
};

#endif // !RTHTTPHEAD_H
